package com.freak.wanandroid.view.viewpager;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewParent;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewpager2.widget.ViewPager2;

/**
 * @author: freak
 * @date: 2022/9/25
 */
public class NestedScrollableHost extends FrameLayout {
    private int touchSlop;
    private float initialX;
    private float initialY;

    private ViewPager2 getParentViewPager() {
        ViewParent viewParent = this.getParent();
        if (!(viewParent instanceof View)) {
            viewParent = null;
        }
        View view;
        for (view = (View) viewParent; view != null && !(view instanceof ViewPager2); view = (View) viewParent) {
            viewParent = view.getParent();
            if (!(viewParent instanceof View)) {
                viewParent = null;
            }
        }
        View var2 = view;
        if (!(view instanceof ViewPager2)) {
            var2 = null;
        }
        return (ViewPager2) var2;
    }

    public NestedScrollableHost(@NonNull Context context) {
        super(context);
        setTouchSlop();
    }

    public NestedScrollableHost(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setTouchSlop();
    }

    private void setTouchSlop() {
        ViewConfiguration viewConfiguration = ViewConfiguration.get(this.getContext());
        if (viewConfiguration == null) {
            return;
        }
        this.touchSlop = viewConfiguration.getScaledTouchSlop();
    }

    public NestedScrollableHost(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setTouchSlop();
    }

    public NestedScrollableHost(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        setTouchSlop();
    }

    private View getChild() {
        return this.getChildCount() > 0 ? this.getChildAt(0) : null;
    }

    private boolean canChildScroll(int orientation, float delta) {
        int direction = -((int) Math.signum(delta));
        View view;
        boolean isCanChildScroll = false;
        switch (orientation) {
            case MotionEvent.ACTION_DOWN:
                view = this.getChild();
                isCanChildScroll = view != null && view.canScrollHorizontally(direction);
                break;
            case MotionEvent.ACTION_MOVE:
                view = this.getChild();
                isCanChildScroll = view != null && view.canScrollVertically(direction);
                break;
            default:
                break;
        }
        return isCanChildScroll;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent motionEvent) {
        this.handleInterceptTouchEvent(motionEvent);
        return super.onInterceptTouchEvent(motionEvent);
    }

    private void handleInterceptTouchEvent(MotionEvent motionEvent) {
        ViewPager2 viewPager2 = this.getParentViewPager();
        if (viewPager2 == null) {
            return;
        }
        int orientation = viewPager2.getOrientation();
        if (canChildScroll(orientation, -1.0F) || canChildScroll(orientation, 1.0F)) {
            switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    this.initialX = motionEvent.getX();
                    this.initialY = motionEvent.getY();
                    this.getParent().requestDisallowInterceptTouchEvent(true);
                    break;
                case MotionEvent.ACTION_MOVE:
                    float dx = motionEvent.getX() - this.initialX;
                    float dy = motionEvent.getY() - this.initialY;
                    boolean isViewPagerHorizontal = orientation == 0;
                    float scaledDx = Math.abs(dx) * (isViewPagerHorizontal ? 0.5F : 1.0F);
                    float scaledDy = Math.abs(dy) * (isViewPagerHorizontal ? 1.0F : 0.5F);
                    if (scaledDx > (float) this.touchSlop || scaledDy > (float) this.touchSlop) {
                        if (isViewPagerHorizontal == scaledDy > scaledDx) {
                            this.getParent().requestDisallowInterceptTouchEvent(false);
                        } else if (this.canChildScroll(orientation, isViewPagerHorizontal ? dx : dy)) {
                            this.getParent().requestDisallowInterceptTouchEvent(true);
                        } else {
                            this.getParent().requestDisallowInterceptTouchEvent(false);
                        }
                    }
                    break;
                default:
                    break;
            }
        }
    }
}
